// 对应版本：easyExcel：2.2.10
package com.zhang.bingmei_incomeexpenditure.config;

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ForceNewRowMergeStrategy implements CellWriteHandler {
    private final int[] mergeColumns;
    private final int startRow;
    private final Map<Integer, String> lastRowValues = new HashMap<>();

    public ForceNewRowMergeStrategy(int startRow, int[] mergeColumns) {
        this.startRow = startRow;
        this.mergeColumns = mergeColumns;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    // 关键改1：方法参数中，CellData类型从WriteCellData<?>改为CellData，无泛型
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder,
                                 WriteTableHolder writeTableHolder,
                                 List<CellData> cellDataList,
                                 Cell cell,
                                 Head head,
                                 Integer relativeRowIndex,
                                 Boolean isHead) {

        // 关键修复1：处理relativeRowIndex为null的情况（非列表填充时可能为null）
        if (relativeRowIndex == null) {
            return; // 非列表数据行不执行合并逻辑
        }

        // 关键修复2：通过cell.getRowIndex()直接获取实际行索引（兼容模板填充场景）
        int rowIndex = cell.getRowIndex();
        int colIndex = cell.getColumnIndex();

        // 修复3：严格判断是否为数据行（跳过表头行和非目标列）
        if (rowIndex <= startRow || !containsColumn(colIndex) || isHead) {
            return;
        }

        String currentValue = getCellValue(cell);
        if (currentValue == null || currentValue.isEmpty()) {
            return;
        }

        String lastValue = lastRowValues.get(colIndex);
        // 修复4：避免lastValue为null时的空指针
        if (lastValue != null && currentValue.equals(lastValue)) {
            mergeCells(writeSheetHolder.getSheet(), rowIndex, colIndex);
        }

        lastRowValues.put(colIndex, currentValue);
    }

    // 以下方法逻辑完全不变，直接复用
    private boolean containsColumn(int colIndex) {
        for (int col : mergeColumns) {
            if (col == colIndex) return true;
        }
        return false;
    }

    private void mergeCells(Sheet sheet, int rowIndex, int colIndex) {
        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
            CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
            if (mergedRegion.getFirstColumn() == colIndex &&
                    mergedRegion.getLastColumn() == colIndex &&
                    mergedRegion.getLastRow() == rowIndex - 1) {

                sheet.removeMergedRegion(i);
                CellRangeAddress newRegion = new CellRangeAddress(
                        mergedRegion.getFirstRow(), rowIndex, colIndex, colIndex);
                sheet.addMergedRegion(newRegion);
                return;
            }
        }

        CellRangeAddress newRegion = new CellRangeAddress(
                rowIndex - 1, rowIndex, colIndex, colIndex);
        sheet.addMergedRegion(newRegion);
    }

    private String getCellValue(Cell cell) {
        if (cell == null) return null;
        try {
            switch (cell.getCellType()) {
                case STRING:
                    return cell.getStringCellValue();
                case NUMERIC:
                    if (DateUtil.isCellDateFormatted(cell)) {
                        return cell.getDateCellValue().toString();
                    } else {
                        double numericValue = cell.getNumericCellValue();
                        if (numericValue == Math.floor(numericValue)) {
                            return String.valueOf((long) numericValue);
                        } else {
                            return String.valueOf(numericValue);
                        }
                    }
                case BOOLEAN:
                    return String.valueOf(cell.getBooleanCellValue());
                case FORMULA:
                    try {
                        return cell.getStringCellValue();
                    } catch (Exception e) {
                        return String.valueOf(cell.getNumericCellValue());
                    }
                default:
                    return "";
            }
        } catch (Exception e) {
            return "";
        }
    }
}

// 对应easyExcel版本 3.3.0
/*
package com.dx.vector.modules.incomeExpenditure.config;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ForceNewRowMergeStrategy implements CellWriteHandler {
    private final int[] mergeColumns;
    private final int startRow;
    private final Map<Integer, String> lastRowValues = new HashMap<>();

    public ForceNewRowMergeStrategy(int startRow, int[] mergeColumns) {
        this.startRow = startRow;
        this.mergeColumns = mergeColumns;
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder,
                                 WriteTableHolder writeTableHolder,
                                 List<WriteCellData<?>> cellDataList,
                                 Cell cell,
                                 Head head,
                                 Integer relativeRowIndex,
                                 Boolean isHead) {

        int rowIndex = cell.getRowIndex();
        int colIndex = cell.getColumnIndex();

        if (rowIndex <= startRow || !containsColumn(colIndex)) {
            return;
        }

        String currentValue = getCellValue(cell);
        if (currentValue == null) {
            return;
        }

        // 检查是否与上一行的值相同
        String lastValue = lastRowValues.get(colIndex);
        if (currentValue.equals(lastValue)) {
            mergeCells(writeSheetHolder.getSheet(), rowIndex, colIndex);
        }

        // 更新最后一行的值
        lastRowValues.put(colIndex, currentValue);
    }

    private boolean containsColumn(int colIndex) {
        for (int col : mergeColumns) {
            if (col == colIndex) return true;
        }
        return false;
    }

    private void mergeCells(Sheet sheet, int rowIndex, int colIndex) {
        // 查找现有的合并区域
        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
            CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
            if (mergedRegion.getFirstColumn() == colIndex &&
                    mergedRegion.getLastColumn() == colIndex &&
                    mergedRegion.getLastRow() == rowIndex - 1) {

                sheet.removeMergedRegion(i);
                CellRangeAddress newRegion = new CellRangeAddress(
                        mergedRegion.getFirstRow(), rowIndex, colIndex, colIndex);
                sheet.addMergedRegion(newRegion);
                return;
            }
        }

        // 创建新的合并区域
        CellRangeAddress newRegion = new CellRangeAddress(
                rowIndex - 1, rowIndex, colIndex, colIndex);
        sheet.addMergedRegion(newRegion);
    }

    private String getCellValue(Cell cell) {
        if (cell == null) return null;
        try {
            switch (cell.getCellType()) {
                case STRING:
                    return cell.getStringCellValue();
                case NUMERIC:
                    if (DateUtil.isCellDateFormatted(cell)) {
                        return cell.getDateCellValue().toString();
                    } else {
                        double numericValue = cell.getNumericCellValue();
                        if (numericValue == Math.floor(numericValue)) {
                            return String.valueOf((long) numericValue);
                        } else {
                            return String.valueOf(numericValue);
                        }
                    }
                case BOOLEAN:
                    return String.valueOf(cell.getBooleanCellValue());
                case FORMULA:
                    try {
                        return cell.getStringCellValue();
                    } catch (Exception e) {
                        return String.valueOf(cell.getNumericCellValue());
                    }
                default:
                    return "";
            }
        } catch (Exception e) {
            return "";
        }
    }
}
*/
